#ifndef TRIANGLE_H_
#define TRIANGLE_H_

#include "Renderable.h"
class Texture;

class Triangle : public Renderable
{
public:
    Triangle() : m_texture(0),m_interpolateNormal(false){}
    Triangle(const Vec3& p0, const Vec3& p1, const Vec3& p2, 
             const Material& m, bool reflect,float reflectance) : Renderable(m,reflect,reflectance),m_texture(0),
    v0(p0),v1(p1),v2(p2),m_interpolateNormal(false){}
    Triangle(const Vec3& p0, const Vec3& p1, const Vec3& p2, 
        const Material& m, bool reflect,float reflectance, bool trans, float op) : 
        Renderable(m,reflect,reflectance,trans,op),m_texture(0),
        v0(p0),v1(p1),v2(p2),m_interpolateNormal(false){}

    virtual bool Hit(const Ray& ray, float& tmin, ContactData& data) const;
#ifdef DEBUGGING
    virtual bool Hit_Debug(const Ray& ray, float& tmin, ContactData& data) const;
#endif
    void Create(const Vec3& p0, const Vec3& p1, const Vec3& p2);
    void CalculateNormal();
    void SetSmootheShadingNormals(  const Vec3& n0,
                                    const Vec3& n1,
                                    const Vec3& n2)
    {
        m_interpolateNormal = true;
        m_n0 = n0;
        m_n1 = n1;
        m_n2 = n2;
    }
    Vec3 InterpolateNormal(float Beta, float Gamma) const;
    Color GetTextureColor( float BETA, float GAMMA ) const;
    Color SampleTexture( float U, float V ) const;
    float InterpolateU( float BETA, float GAMMA ) const;
    float InterpolateV( float BETA, float GAMMA ) const;
    //Z must always be 0, lol
    void SetUVs(const Vec3& vert0,const Vec3& vert1,const Vec3& vert2){m_uv0 = vert0;m_uv1 = vert1;m_uv2 = vert2;}
    void SetTexture(Texture* t){m_texture = t; if(t){m_textured = true;}}
    virtual void CalculateBox()
    {
        m_hasValidBox = true;
        Vec3 min(v2);
        //min - X
        if(v0.m_x <= v1.m_x && v0.m_x <= v2.m_x)
            min.m_x = v0.m_x;
        else if(v1.m_x <= v0.m_x && v1.m_x <= v2.m_x)
            min.m_x = v1.m_x;
        //min Y
        if(v0.m_y <= v1.m_y && v0.m_y <= v2.m_y)
            min.m_y = v0.m_y;
        else if(v1.m_y <= v0.m_y && v1.m_y <= v2.m_y)
            min.m_y = v1.m_y;
        //min - Z
        if(v0.m_z <= v1.m_z && v0.m_z <= v2.m_z)
            min.m_z = v0.m_z;
        else if(v1.m_z <= v0.m_z && v1.m_z <= v2.m_z)
            min.m_z = v1.m_z;
        Vec3 max(v2);
        //max - X
        if(v0.m_x >= v1.m_x && v0.m_x >= v2.m_x)
            max.m_x = v0.m_x;
        else if(v1.m_x >= v0.m_x && v1.m_x >= v2.m_x)
            max.m_x = v1.m_x;
        //max Y
        if(v0.m_y >= v1.m_y && v0.m_y >= v2.m_y)
            max.m_y = v0.m_y;
        else if(v1.m_y >= v0.m_y && v1.m_y >= v2.m_y)
            max.m_y = v1.m_y;
        //max - Z
        if(v0.m_z >= v1.m_z && v0.m_z >= v2.m_z)
            max.m_z = v0.m_z;
        else if(v1.m_z >= v0.m_z && v1.m_z >= v2.m_z)
            max.m_z = v1.m_z;
        m_box.SetValues(min.m_x-0.001f,min.m_y-0.001f,min.m_z-0.001f,
                        max.m_x+0.001f,max.m_y+0.001f,max.m_z+0.001f);

        //Good place to add the debug string, as the triangle must have
        //been created by now!
#ifdef DEBUGGING
        m_information += "Class Triangle: \n";
#endif
    }
    void SetNormal(const Vec3& v){m_normal = v;}
private:
    //normal, standalone useage
    Vec3 v0;
    Vec3 m_uv0;
    Vec3 v1;
    Vec3 m_uv1;
    Vec3 v2;
    Vec3 m_uv2;
    Vec3 m_normal;
    //textured?
    Texture* m_texture;    
    //smoothed?
    bool m_interpolateNormal;
    Vec3 m_n0, m_n1, m_n2;
};
#endif